package org.jeecg.common.util.mputil;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 3表级联操作
 * p是主表c是子表
 *
 * @author zjarlin
 * @since 2023/2/26 09:18
 */
//@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class MpUtil3<P, C, C1> {

    protected IService<P> ps;

    protected IService<C> cs;

    protected IService<C1> cs1;

    public static <P, C, C1> MpUtil3<P, C, C1> of(IService<P> ps, IService<C> cs, IService<C1> cs1) {
        return new MpUtil3<>(ps, cs, cs1);
    }

    public boolean pSave(P p, List<C> childColl, List<C1> childColl1, Function<P, String> getPidFun
            , BiConsumer<C, String> cSetPkFun
            , BiConsumer<C1, String> c1SetPkFun
    ) {
        BiConsumer<C, P> tConsumer = (child, par) -> cSetPkFun.accept(child, String.valueOf(getPidFun.apply(par)));
        BiConsumer<C1, P> tConsumer1 = (child1, par) -> c1SetPkFun.accept(child1, String.valueOf(getPidFun.apply(par)));
        boolean b;
        try {
            b = pSave(p, childColl, childColl1, tConsumer, tConsumer1);
        } catch (Exception e) {
            return false;
        }
        return b;

    }

    /**
     * 级联新增
     *
     * @param p
     * @param childColl  子表
     * @param childColl1 孩子coll1
     * @param cSetFun    c组有趣
     * @param c1SetFun   c1组有趣 入参
     * @return boolean
     * @author zjarlin
     * @since 2023/03/16
     */
    public boolean pSave(P p, Collection<C> childColl, Collection<C1> childColl1, BiConsumer<C, P> cSetFun, BiConsumer<C1, P> c1SetFun) {
        boolean save = ps.save(p);
        return save && cSave(p, childColl, childColl1, cSetFun, c1SetFun);
    }

    /**
     * 子表新增
     *
     * @param p         p
     * @param childColl 孩子科尔
     * @param setFun    设置有趣 入参
     * @return boolean
     * @author zjarlin
     * @since 2023/03/01
     */
    public boolean cSave(P p, Collection<C> childColl, Collection<C1> childColl1, BiConsumer<C, P> setFun, BiConsumer<C1, P> c1SetFun) {
        Consumer<C> cConsumer = child -> setFun.accept(child, p);
        childColl.forEach(cConsumer);
        Consumer<C1> c1Consumer = child -> c1SetFun.accept(child, p);
        childColl.forEach(cConsumer);
        childColl1.forEach(c1Consumer);
        boolean b = cs.saveBatch(childColl);
        boolean b1 = cs1.saveBatch(childColl1);
        return b && b1;
    }

    public boolean pRemove(Serializable pid, SFunction<C, String> cGetPidFun, SFunction<C1, String> c1GetPidFun) {
        boolean b = ps.removeById(pid);
        boolean b1 = cRemove(pid, cGetPidFun, c1GetPidFun);
        return b && b1;
    }

    public boolean pRemoveBatch(Collection<? extends Serializable> pid, SFunction<C, String> cGetPidFun, SFunction<C1, String> c1GetPidFun) {
        boolean b1 = ps.removeByIds(pid);
        boolean b = cRemoveBatch(pid, cGetPidFun, c1GetPidFun);
        return b1 && b;
    }

    public boolean cRemove(Serializable pid, SFunction<C, String> cGetPidFun, SFunction<C1, String> c1GetPidFun) {
        LambdaQueryWrapper<C> eq = Wrappers.<C>lambdaQuery().eq(cGetPidFun, pid);
        LambdaQueryWrapper<C1> eq1 = Wrappers.<C1>lambdaQuery().eq(c1GetPidFun, pid);
        boolean remove = cs.remove(eq);
        boolean remove1 = cs1.remove(eq1);
        return remove && remove1;
    }

    public boolean cRemoveBatch(Collection<? extends Serializable> pid, SFunction<C, String> cGetPidFun, SFunction<C1, String> c1GetPidFun) {
        boolean remove2 = cs.lambdaUpdate().in(cGetPidFun, pid).remove();
        boolean remove3 = cs1.lambdaUpdate().in(c1GetPidFun, pid).remove();
        return remove2 && remove3;
    }

    public boolean pUpdate(P p, Collection<C> childColl, Collection<C1> childColl1, Function<P, String> pgetPidFun, SFunction<C, String> cgetPidFun, SFunction<C1, String> c1GetPidFun, BiConsumer<C, String> csetPkFun, BiConsumer<C1, String> c1SetPkFun) {
        boolean b = ps.updateById(p);
        String apply = pgetPidFun.apply(p);
        boolean b2 = cRemove(apply, cgetPidFun, c1GetPidFun);
        boolean b3 = cSave(p, childColl, childColl1, pgetPidFun, csetPkFun, c1SetPkFun);
        return b && b2 && b3;
    }

    /**
     * c保存
     *
     * @param p         p
     * @param childColl 孩子科尔
     * @param getPidFun 得到pid有趣
     * @param setPkFun  组pk有趣 入参
     * @return boolean
     * @author zjarlin
     * @since 2023/03/01
     */
    public boolean cSave(P p, Collection<C> childColl, Collection<C1> childColl1, Function<P, String> getPidFun, BiConsumer<C, String> setPkFun, BiConsumer<C1, String> c1SetPkFun) {
        BiConsumer<C, P> tConsumer = (child, par) -> setPkFun.accept(child, String.valueOf(getPidFun.apply(par)));
        BiConsumer<C1, P> t1Consumer = (child, par) -> c1SetPkFun.accept(child, String.valueOf(getPidFun.apply(par)));
        return cSave(p, childColl, childColl1, tConsumer, t1Consumer);

    }

}
